package com.rw.tool.util.io.file.json;

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.rw.tool.util.io.file.property.*;
import com.rw.tool.util.io.file.wrapper.FileLambdaQueryWrapper;
import com.rw.tool.util.io.file.wrapper.LambdaGetter;
import com.rw.tool.util.json.JsonUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 使用json来获取bean属性的属性解析器
 *
 * @param <T> 存放的javabean
 */
public class JsonBeanParser<T> extends IdGetterBeanParser<T, BeanPropertyDefinition> {
    /**
     * 声明一个json的属性解析器
     *
     * @param idListGetter 自定义id属性获取
     */
    public JsonBeanParser(IdListGetter<BeanPropertyDefinition> idListGetter) {
        super(idListGetter);
    }

    /**
     * 声明一个json的属性解析器，默认使用@FileId注解来标识id属性
     */
    public JsonBeanParser() {
        super(JsonBeanParser::getIdList);
    }

    /**
     * 根据properties获取里面的所有ID的getter方法
     */
    protected static List<IdProperty<BeanPropertyDefinition>> getIdList(List<BeanPropertyDefinition> properties) {
        List<IdProperty<BeanPropertyDefinition>> idGetterList = new ArrayList<>();
        // 遍历所有属性
        for (BeanPropertyDefinition property : properties) {
            AnnotatedMethod getter = property.getGetter();
            FileId fileId = getter.getAnnotation(FileId.class);
            // 如果没有注解，则跳过
            if (fileId == null) {
                continue;
            }

            // 构造id属性
            IdProperty<BeanPropertyDefinition> idProperty = new IdProperty<>(fileId.autoIncrement(), property);
            idGetterList.add(idProperty);
        }

        return idGetterList;
    }

    /**
     * 根据class获取里面的所有属性
     *
     * @param tClass class对象
     * @return 属性列表
     */
    @Override
    protected List<BeanPropertyDefinition> getAllField(Class<T> tClass) {
        // 获取mapper，得到javaType
        ObjectMapper mapper = JsonUtil.getMapper();
        JavaType type = mapper.constructType(tClass);

        // 从mapper中取出序列化设置
        SerializationConfig serializationConfig = mapper.getSerializationConfig();
        // 用这个序列化设置解析这个类的信息，并且取出里面的所有属性
        BeanDescription beanDescription = serializationConfig.introspect(type);
        return beanDescription.findProperties();
    }

    /**
     * 解析json的属性，封装为自定义的接口
     *
     * @param beanPropertyDefinition json的属性
     * @return 自定义的接口
     */
    @Override
    protected FileProperty<T> toFileProperty(BeanPropertyDefinition beanPropertyDefinition, boolean autoIncrement) {
        // 获取属性名
        String name = beanPropertyDefinition.getName();
        // 声明属性的访问器
        JsonPropertyVisitor<T> jsonPropertyVisitor = new JsonPropertyVisitor<>(beanPropertyDefinition);

        return new FileProperty<>(name, autoIncrement, jsonPropertyVisitor);
    }

    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param idList          id列表
     * @param autoIncrementId 自增id
     */
    public static <T> JsonBeanParser<T> ofIdFilter(List<String> idList, List<String> autoIncrementId) {
        return new JsonBeanParser<>(new FilterIdGetter<>(idList, autoIncrementId, BeanPropertyDefinition::getName));
    }

    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param id            id
     * @param autoIncrement 是否自增
     */
    public static <T> JsonBeanParser<T> ofIdFilter(String id, boolean autoIncrement) {
        return new JsonBeanParser<>(new FilterIdGetter<>(id, autoIncrement, BeanPropertyDefinition::getName));
    }

    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param idList id列表
     */
    public static <T> JsonBeanParser<T> ofIdFilter(List<String> idList) {
        return new JsonBeanParser<>(new FilterIdGetter<>(idList, BeanPropertyDefinition::getName));
    }


    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param id id
     */
    public static <T> JsonBeanParser<T> ofIdFilter(String id) {
        return new JsonBeanParser<>(new FilterIdGetter<>(id, BeanPropertyDefinition::getName));
    }


    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param lambdaIdList          id列表
     * @param lambdaAutoIncrementId 自增id
     */
    public static <T> JsonBeanParser<T> ofLambdaIdFilter(List<LambdaGetter<T>> lambdaIdList,
                                                         List<LambdaGetter<T>> lambdaAutoIncrementId) {
        List<String> idList = lambdaIdList.stream()
                .map(FileLambdaQueryWrapper::parseLambdaName)
                .collect(Collectors.toList());

        List<String> autoIncrementId = lambdaAutoIncrementId.stream()
                .map(FileLambdaQueryWrapper::parseLambdaName)
                .collect(Collectors.toList());

        return ofIdFilter(idList, autoIncrementId);
    }

    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param lambdaId      id
     * @param autoIncrement 是否自增
     */
    public static <T> JsonBeanParser<T> ofLambdaIdFilter(LambdaGetter<T> lambdaId, boolean autoIncrement) {
        return ofIdFilter(FileLambdaQueryWrapper.parseLambdaName(lambdaId), autoIncrement);
    }

    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param lambdaIdList id列表
     */
    public static <T> JsonBeanParser<T> ofLambdaIdFilter(List<LambdaGetter<T>> lambdaIdList) {
        List<String> idList = lambdaIdList.stream()
                .map(FileLambdaQueryWrapper::parseLambdaName)
                .collect(Collectors.toList());

        return ofIdFilter(idList);
    }


    /**
     * 声明一个根据id过滤的过滤器
     *
     * @param lambdaId id
     */
    public static <T> JsonBeanParser<T> ofLambdaIdFilter(LambdaGetter<T> lambdaId) {
        return ofIdFilter(FileLambdaQueryWrapper.parseLambdaName(lambdaId));
    }
}
